﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using Common.Utilities;
using Common.Utilities.Dispatcher;

namespace Workflows.Components.CommandLineUtilities
{
    [Serializable]
    public class CommandLineInstruction:InstructionBase
    {
        #region fields & props
        private string _ProgramFilePath;
        /// <summary></summary>
        public string ProgramFilePath
        {
            get
            {
                return this._ProgramFilePath;
            }
            set
            {
                this._ProgramFilePath = value;
            }
        }
        private string _ArgTemplate;
        /// <summary></summary>
        public string ArgTemplate
        {
            get
            {
                return this._ArgTemplate;
            }
            set
            {
                this._ArgTemplate = value;
            }
        }
        private Dictionary<string,string> _Options;
        /// <summary></summary>
        public Dictionary<string, string> Options
        {
            get
            {
                return this._Options;
            }
            set
            {
                this._Options = value;
            }
        }
        #endregion

        public CommandLineInstruction():base(Guid.Empty,Guid.Empty)
        {
            this._ProgramFilePath = string.Empty;
            this._ArgTemplate = string.Empty;
            this._Options = null;
        }

        public CommandLineInstruction(Guid componentID, Guid jobTicketID,
            string progFilePath,
            string argTemplate,
            Dictionary<string,string> options) 
            : base(componentID, jobTicketID)
        {
            this._ProgramFilePath = progFilePath;
            this._ArgTemplate = argTemplate;
            this._Options = options;
        }

        public override XmlNode Serialize(ref XmlDocument xDoc, ref XmlNode parentNode)
        {
            XmlNode xNode = XmlDataUtil.AddElement(ref xDoc, parentNode, "Instruction");
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "Type", this.GetType().FullName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ComponentID", this.OwnerComponentID.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "WorkerID", this.OwnerWorkerInstanceID.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SubmitTime", this.SubmitTime.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "StartTime", this.StartTime.ToString());

            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ProgramFilePath", this.ProgramFilePath);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ArgumentTemplate", this.ArgTemplate);
            if (this.Options != null && this.Options.Count > 0)
            {
                XmlNode argNameRootNode = XmlDataUtil.AddElement(ref xDoc, xNode, "Options");
                foreach (string opName in this.Options.Keys)
                {
                    XmlNode opNode = XmlDataUtil.AddElement(ref xDoc, argNameRootNode, "Option");
                    XmlDataUtil.UpdateAttribute(ref xDoc,opNode,"Name",opName);
                    XmlDataUtil.UpdateAttribute(ref xDoc, opNode, "Value", this.Options[opName]);
                }
            }

            return xNode;
        }

        public override InstructionBase Instantiate(XmlNode xNode)
        {
            if (xNode.Attributes.GetNamedItem("Type").Value == this.GetType().FullName)
            {
                CommandLineInstruction instruction = new CommandLineInstruction();
                instruction.OwnerComponentID = new Guid(xNode.Attributes.GetNamedItem("ComponentID").Value);
                instruction.OwnerWorkerInstanceID = new Guid(xNode.Attributes.GetNamedItem("WorkerID").Value);
                instruction.SubmitTime = DateTime.Parse(xNode.Attributes.GetNamedItem("SubmitTime").Value);
                instruction.StartTime = DateTime.Parse(xNode.Attributes.GetNamedItem("StartTime").Value);

                instruction.ProgramFilePath = xNode.Attributes.GetNamedItem("ProgramFilePath").Value;
                instruction.ArgTemplate = xNode.Attributes.GetNamedItem("ArgumentTemplate").Value;
                instruction.Options = null;
                XmlNodeList opNodes = xNode.SelectNodes("Options/Option");
                if (opNodes != null && opNodes.Count > 0)
                {
                    instruction.Options=new Dictionary<string, string>();
                    foreach (XmlNode opNode in opNodes)
                    {
                        string name = opNode.Attributes.GetNamedItem("Name").Value;
                        string value = opNode.Attributes.GetNamedItem("Value").Value;
                        instruction.Options.Add(name, value);
                    }
                }

                return instruction;
            }
            else
            {
                throw new Exception("Unable to instantiate instruction: invalid type specified in xml node");
            }
        }
    }
}
